package ca.concordia.soen6011.impl;

import java.util.Date;

import ca.concordia.soen6011.commons.Helpers;
import ca.concordia.soen6011.interfaces.MathFunction;
import ca.concordia.soen6011.Result;


public class XPowerX implements MathFunction {
	static double pow = 1.0;
	@Override
	public Result compute(double x, double precision) {
        
		long start = System.currentTimeMillis();
		Double functionResult = null;
	    if(Helpers.isInteger(x))
		functionResult = powerX(x,x);
	    else functionResult = exponential(x,precision);
		long end = System.currentTimeMillis();
		// result object to show output on console 
		Result result = new Result();
		result.setComputationTime(end-start);
		result.setPrecison(precision);
		result.setOutput(functionResult);
		//System.out.println(functionResult);
		return result;
	}

	@Override
	public String getName() {
		return "x power(x)";
	}
	
	public static double powerX(double x, double n) {
		if (x == 0)
		      throw new IllegalArgumentException("x is zero");
		   else if (n == 0)
		      return 1;
		   else if (n > 0)
		      return x * powerX(x, n-1);
		   else 
		      return 1/powerX(x, -n);
	}
/*/
 * Function calculate exponential of give value
 * @param 
 * @x
 * @precision
 * 
 * @output
 */
	private static double exponential(double x, double precision){
		double result=0.0;
		double temp =0;
		try {
			temp = Helpers.ln(x, 0.0000000001);
		} catch (Exception e) {
			
		}
		double sum = x*temp;
		for (int i=0; ; i++) {
			double temp_a = Helpers.power(sum,i)/Helpers.factorial(i);
	          	if (Helpers.reachedRequiredPrecision(temp_a, precision))
				break;
			else
				result +=temp_a;
        }
		return result;
	}
	
	@Override
	public void validate(double x, double precision) throws Exception {
		// TODO Auto-generated method stub
		
	}
	
	}
